package com.unswift.window.factory;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.KeyListener;
import java.lang.reflect.Array;
import java.util.HashSet;
import java.util.Set;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.Border;

import com.unswift.utils.ObjectUtils;
import com.unswift.window.editor.Editor;
import com.unswift.window.editor.EditorDocument;
import com.unswift.window.editor.EditorLine;
import com.unswift.window.extend.Attribute;
import com.unswift.window.extend.Form;
import com.unswift.window.extend.InputText;
import com.unswift.window.listener.InputDocument;

public final class FormFactory {
	
	public static GridBagConstraints constraints;
	
	public static Form create(Color bgColor, Border border, int column, int row, Integer paddingTop){
		Form form=PanelFactory.createForm(bgColor, border, null);
		formLayout(form, column, row);
		initConstraints(paddingTop);
		return form;
	}
	
	private static void initConstraints(Integer paddingTop) {
		constraints = new GridBagConstraints();
		constraints.insets=new Insets(ObjectUtils.init(paddingTop, 15), 0, 0, 0);
		constraints.fill=GridBagConstraints.HORIZONTAL;
	}
	
	public static Form create2(Color bgColor, Border border, int column, int row, Integer paddingTop){
		Form form=PanelFactory.createForm(bgColor, null, null);
		formLayout2(form, column, row);
		initConstraints(paddingTop);
		return form;
	}

	public static GridBagLayout formLayout(JPanel form, int column, int row){
		GridBagLayout layout = new GridBagLayout();
		int[] columnWidths=new int[column+1];
		for (int i = 0; i <= column; i++) {
			columnWidths[i]=0;
		}
		layout.columnWidths=columnWidths;
		int[] rowHeights=new int[row];
		for (int i = 0; i < row; i++) {
			rowHeights[i]=35;
		}
		layout.rowHeights=rowHeights;
		if(column==2){
			layout.columnWeights=new double[]{0.15, 0.7, 0.15};
		}
		form.setLayout(layout);
		return layout;
	}
	
	public static GridBagLayout formLayout2(JPanel form, int column, int row){
		GridBagLayout layout = new GridBagLayout();
		int[] columnWidths=new int[column+1];
		for (int i = 0; i <= column; i++) {
			columnWidths[i]=0;
		}
		layout.columnWidths=columnWidths;
		int[] rowHeights=new int[row];
		for (int i = 0; i < row; i++) {
			rowHeights[i]=20;
		}
		layout.rowHeights=rowHeights;
		if(column==2){
			layout.columnWeights=new double[]{0.05, 0.95};
		}
		form.setLayout(layout);
		return layout;
	}
	
	public static void addRow(JPanel form, int row, String label, JComponent editComp, Integer rowHeight, Integer fieldWidth){
		if(ObjectUtils.isNotEmpty(rowHeight)){
			GridBagLayout layout = (GridBagLayout)form.getLayout();
			layout.rowHeights[row]=rowHeight;
			int width=(int)(fieldWidth*layout.columnWeights[1]);
			editComp.setPreferredSize(new Dimension(width, rowHeight));
		}
		constraints.gridx=0;
		constraints.gridy=row;
		form.add(createLabel(label, JLabel.RIGHT, null), constraints);
		constraints.gridx=1;
		constraints.gridy=row;
		form.add(editComp, constraints);
	}
	
	public static JLabel createLabel(String labelText, int align, String tips){
		JLabel label = new JLabel(labelText, align);
		if(ObjectUtils.isNotEmpty(tips)){
			label.setToolTipText(tips);
		}
		return label;
	}
	
	public static Insets defaultMargin(){
		return createMargin(0, 5, 0, 5);
	}
	
	public static Insets createMargin(int top, int left, int bottom, int right){
		return new Insets(top, left, bottom, right);
	}
	
	public static JTextField createFormInput(Attribute attribute){
		String value = attribute.get(Attribute.ATTRIBUTE_FORM_VALUE);
		InputText text=new InputText();
		if(attribute.exists(Attribute.ATTRIBUTE_FORM_INPUT_DOCUMENT)){
			InputDocument document = attribute.get(Attribute.ATTRIBUTE_FORM_INPUT_DOCUMENT);
			document.setInitValue(value);
			document.setInput(text);
			text.setDocument(document);
		}
		if(attribute.exists(Attribute.ATTRIBUTE_FORM_COLUMNS)){
			text.setColumns(attribute.get(Attribute.ATTRIBUTE_FORM_COLUMNS));
		}
		text.setText(value);
		Boolean editable=attribute.get(Attribute.ATTRIBUTE_FORM_EDITABLE);
		if(ObjectUtils.isNotEmpty(editable)){
			text.setEditable(editable);
		}
		Boolean enabled=attribute.get(Attribute.ATTRIBUTE_FORM_ENABLED);
		if(ObjectUtils.isNotEmpty(enabled)){
			text.setEnabled(enabled);
		}
		if(attribute.exists(Attribute.ATTRIBUTE_FORM_HEIGHT)){
			text.setPreferredSize(new Dimension(0, attribute.get(Attribute.ATTRIBUTE_FORM_HEIGHT)));
		}else{
			text.setPreferredSize(new Dimension(0, 25));
		}
		Insets insets=attribute.get(Attribute.ATTRIBUTE_FORM_MARGIN);
		if(ObjectUtils.isNotEmpty(insets)){
			text.setMargin(insets);
		}
		if(attribute.exists(Attribute.ATTRIBUTE_FORM_FOCUS)){
			text.setRequestFocusEnabled(attribute.get(Attribute.ATTRIBUTE_FORM_FOCUS));
		}
		if(attribute.exists(Attribute.ATTRIBUTE_FORM_COLOR)){
			text.setForeground(attribute.get(Attribute.ATTRIBUTE_FORM_COLOR));
		}
		if(attribute.exists(Attribute.ATTRIBUTE_FORM_BORDER)){
			text.setBorder(attribute.get(Attribute.ATTRIBUTE_FORM_BORDER));
		}
		if(attribute.exists(Attribute.ATTRIBUTE_FORM_PLACEHOLDER)){
			text.setPlaceholder(attribute.get(Attribute.ATTRIBUTE_FORM_PLACEHOLDER));
		}
		if(attribute.exists(Attribute.ATTRIBUTE_FORM_KEY_LISTENER)){
			KeyListener keyListener = attribute.get(Attribute.ATTRIBUTE_FORM_KEY_LISTENER);
			text.addKeyListener(keyListener);
		}
		return text;
	}
	
	@SuppressWarnings("unchecked")
	public static <T> JComboBox<T> createFormSelect(Attribute attribute){
		JComboBox<T> select=new JComboBox<T>((T[])attribute.get(Attribute.ATTRIBUTE_FORM_SELECT_OPTIONS));
		Boolean editable=attribute.get(Attribute.ATTRIBUTE_FORM_EDITABLE);
		if(ObjectUtils.isNotEmpty(editable)){
			select.setEditable(editable);
		}
		Boolean enabled=attribute.get(Attribute.ATTRIBUTE_FORM_ENABLED);
		if(ObjectUtils.isNotEmpty(enabled)){
			select.setEnabled(enabled);
		}
		String defaultValue=attribute.get(Attribute.ATTRIBUTE_FORM_VALUE);
		if(ObjectUtils.isNotNull(defaultValue)){
			select.setSelectedItem(defaultValue);
		}
		Boolean heightAuto=attribute.get(Attribute.ATTRIBUTE_FORM_HEIGHT_AUTO);
		if(ObjectUtils.isEmpty(heightAuto) || !heightAuto){
			if(attribute.exists(Attribute.ATTRIBUTE_FORM_HEIGHT)){
				select.setPreferredSize(new Dimension(0, attribute.get(Attribute.ATTRIBUTE_FORM_HEIGHT)));
			}else{
				select.setPreferredSize(new Dimension(0, 25));
			}
		}
		if(attribute.exists(Attribute.ATTRIBUTE_FORM_FOCUS)){
			select.setRequestFocusEnabled(attribute.get(Attribute.ATTRIBUTE_FORM_FOCUS));
		}
		if(attribute.exists(Attribute.ATTRIBUTE_FORM_SELECT_LISTENER)){
			select.addItemListener(attribute.get(Attribute.ATTRIBUTE_FORM_SELECT_LISTENER));
		}
		return select;
	}
	
	public static Editor createFormArea(Attribute attribute){
		boolean editable = attribute.get(Attribute.ATTRIBUTE_FORM_EDITABLE);
		Editor area=new Editor(attribute.get(Attribute.ATTRIBUTE_FORM_ACTION), new EditorDocument(), editable);
		if(attribute.exists(Attribute.ATTRIBUTE_FORM_EDITOR_LINES) && (boolean)attribute.get(Attribute.ATTRIBUTE_FORM_EDITOR_LINES)){
			area.setBorder(new EditorLine(area));
		}
		area.setText(attribute.get(Attribute.ATTRIBUTE_FORM_VALUE));
		Boolean enabled=attribute.get(Attribute.ATTRIBUTE_FORM_ENABLED);
		if(ObjectUtils.isNotEmpty(enabled)){
			area.setEnabled(enabled);
		}
		Insets insets=attribute.get(Attribute.ATTRIBUTE_FORM_MARGIN);
		if(ObjectUtils.isNotEmpty(insets)){
			area.setMargin(insets);
		}
		if(attribute.exists(Attribute.ATTRIBUTE_FORM_FOCUS)){
			area.setRequestFocusEnabled(attribute.get(Attribute.ATTRIBUTE_FORM_FOCUS));
		}
		if(attribute.exists(Attribute.ATTRIBUTE_FORM_COLOR)){
			area.setForeground(attribute.get(Attribute.ATTRIBUTE_FORM_COLOR));
		}
		if(attribute.exists(Attribute.ATTRIBUTE_FORM_BGCOLOR)){
			area.setBackground(attribute.get(Attribute.ATTRIBUTE_FORM_BGCOLOR));
		}
		if(attribute.exists(Attribute.ATTRIBUTE_FORM_BORDER)){
			area.setBorder(attribute.get(Attribute.ATTRIBUTE_FORM_BORDER));
		}
		return area;
	}
	
	public static JTextArea createFormArea2(Attribute attribute){
		JTextArea area=new JTextArea((String)attribute.get(Attribute.ATTRIBUTE_FORM_VALUE));
		area.setLineWrap(true);
		area.setWrapStyleWord(true);
		boolean editable = attribute.get(Attribute.ATTRIBUTE_FORM_EDITABLE);
		if(ObjectUtils.isNotEmpty(editable)){
			area.setEditable(editable);
		}
		Boolean enabled=attribute.get(Attribute.ATTRIBUTE_FORM_ENABLED);
		if(ObjectUtils.isNotEmpty(enabled)){
			area.setEnabled(enabled);
		}
		Insets insets=attribute.get(Attribute.ATTRIBUTE_FORM_MARGIN);
		if(ObjectUtils.isNotEmpty(insets)){
			area.setMargin(insets);
		}
		if(attribute.exists(Attribute.ATTRIBUTE_FORM_FOCUS)){
			area.setRequestFocusEnabled(attribute.get(Attribute.ATTRIBUTE_FORM_FOCUS));
		}
		if(attribute.exists(Attribute.ATTRIBUTE_FORM_COLOR)){
			area.setForeground(attribute.get(Attribute.ATTRIBUTE_FORM_COLOR));
		}
		if(attribute.exists(Attribute.ATTRIBUTE_FORM_BGCOLOR)){
			area.setBackground(attribute.get(Attribute.ATTRIBUTE_FORM_BGCOLOR));
		}
		if(attribute.exists(Attribute.ATTRIBUTE_FORM_BORDER)){
			area.setBorder(attribute.get(Attribute.ATTRIBUTE_FORM_BORDER));
		}
		return area;
	}
	
	public static JPanel createFormCheck(Attribute attribute){
		JPanel panel=PanelFactory.create(Color.WHITE, null, new FlowLayout(FlowLayout.LEFT));
		Object checkValue=attribute.get(Attribute.ATTRIBUTE_FORM_VALUE);
		String[] checkValues;
		if(checkValue instanceof String){
			checkValues=new String[]{(String)checkValue};
			
		}else{
			checkValues=(String[])checkValue;
		}
		Object selected=attribute.get(Attribute.ATTRIBUTE_FORM_SELECT);
		Set<String> selecteds=new HashSet<String>();
		if(ObjectUtils.isNotEmpty(selected)){
			if(selected instanceof String){
				selecteds.add((String)selected);
			}else{
				int length=Array.getLength(selected);
				for (int i = 0; i < length; i++) {
					selecteds.add((String)Array.get(selected, i));
				}
			}
		}
		JCheckBox check;
		for (String value : checkValues) {
			check=new JCheckBox(value);
			if(attribute.exists(Attribute.ATTRIBUTE_FORM_ACTION)){
				check.setActionCommand(attribute.get(attribute.get(Attribute.ATTRIBUTE_FORM_ACTION)));
			}
			if(selecteds.contains(value)){
				check.setSelected(true);
			}
			Boolean enabled=attribute.get(Attribute.ATTRIBUTE_FORM_ENABLED);
			if(ObjectUtils.isNotEmpty(enabled)){
				check.setEnabled(enabled);
			}
			if(attribute.exists(Attribute.ATTRIBUTE_FORM_FOCUS)){
				check.setRequestFocusEnabled(attribute.get(Attribute.ATTRIBUTE_FORM_FOCUS));
			}
			if(attribute.exists(Attribute.ATTRIBUTE_FORM_BGCOLOR)){
				check.setBackground(attribute.get(Attribute.ATTRIBUTE_FORM_BGCOLOR));
			}
			panel.add(check);
		}
		
		return panel;
	}
	
	public static JPanel createFormRadio(Attribute attribute){
		JPanel panel=PanelFactory.create(Color.WHITE, null, new FlowLayout(FlowLayout.LEFT));
		Object checkValue=attribute.get(Attribute.ATTRIBUTE_FORM_VALUE);
		String[] checkValues;
		if(checkValue instanceof String){
			checkValues=new String[]{(String)checkValue};
			
		}else{
			checkValues=(String[])checkValue;
		}
		Object selected=attribute.get(Attribute.ATTRIBUTE_FORM_SELECT);
		Set<String> selecteds=new HashSet<String>();
		if(ObjectUtils.isNotEmpty(selected)){
			if(selected instanceof String){
				selecteds.add((String)selected);
			}else{
				int length=Array.getLength(selected);
				for (int i = 0; i < length; i++) {
					selecteds.add((String)Array.get(selected, i));
				}
			}
		}
		JRadioButton radio;
		for (String value : checkValues) {
			radio=new JRadioButton(value);
			if(attribute.exists(Attribute.ATTRIBUTE_FORM_ACTION)){
				radio.setActionCommand(attribute.get(attribute.get(Attribute.ATTRIBUTE_FORM_ACTION)));
			}
			if(selecteds.contains(value)){
				radio.setSelected(true);
			}
			Boolean enabled=attribute.get(Attribute.ATTRIBUTE_FORM_ENABLED);
			if(ObjectUtils.isNotEmpty(enabled)){
				radio.setEnabled(enabled);
			}
			if(attribute.exists(Attribute.ATTRIBUTE_FORM_FOCUS)){
				radio.setRequestFocusEnabled(attribute.get(Attribute.ATTRIBUTE_FORM_FOCUS));
			}
			if(attribute.exists(Attribute.ATTRIBUTE_FORM_BGCOLOR)){
				radio.setBackground(attribute.get(Attribute.ATTRIBUTE_FORM_BGCOLOR));
			}
			panel.add(radio);
		}
		
		return panel;
	}
	
	public static JPanel createFormFile(Attribute attribute){
		JPanel file=PanelFactory.create(Color.WHITE, null, new BorderLayout());
		JTextField text=new JTextField(attribute.get(Attribute.ATTRIBUTE_FORM_VALUE));
		Boolean editable=attribute.get(Attribute.ATTRIBUTE_FORM_EDITABLE);
		if(ObjectUtils.isNotEmpty(editable)){
			text.setEditable(editable);
		}
		Boolean enabled=attribute.get(Attribute.ATTRIBUTE_FILECHOOSE_ENABLED);
		if(ObjectUtils.isNotEmpty(enabled)){
			text.setEnabled(enabled);
		}
		if(attribute.exists(Attribute.ATTRIBUTE_FORM_HEIGHT)){
			text.setPreferredSize(new Dimension(0, attribute.get(Attribute.ATTRIBUTE_FORM_HEIGHT)));
		}else{
			text.setPreferredSize(new Dimension(0, 25));
		}
		Insets insets=attribute.get(Attribute.ATTRIBUTE_FORM_MARGIN);
		if(ObjectUtils.isNotEmpty(insets)){
			text.setMargin(insets);
		}
		if(attribute.exists(Attribute.ATTRIBUTE_FORM_FOCUS)){
			text.setRequestFocusEnabled(attribute.get(Attribute.ATTRIBUTE_FORM_FOCUS));
		}
		if(attribute.exists(Attribute.ATTRIBUTE_FORM_COLOR)){
			text.setForeground(attribute.get(Attribute.ATTRIBUTE_FORM_COLOR));
		}
		file.add(text, BorderLayout.CENTER);
		JButton fileButton=ButtonFactory.createButton(
			Attribute.create()
			.put(Attribute.ATTRIBUTE_BUTTON_ORIGINAL, true)
			.put(Attribute.ATTRIBUTE_BUTTON_NAME, "选择")
			.put(Attribute.ATTRIBUTE_BUTTON_ACTION, attribute.get(Attribute.ATTRIBUTE_FORM_ACTION))
			.put(Attribute.ATTRIBUTE_BUTTON_OPAQUE, true)
			.put(Attribute.ATTRIBUTE_BUTTON_MARGIN, null)
			.put(Attribute.ATTRIBUTE_BUTTON_PADDING, null)
			.put(Attribute.ATTRIBUTE_BUTTON_SIZE, attribute.get(Attribute.ATTRIBUTE_BUTTON_SIZE))
			.put(Attribute.ATTRIBUTE_BUTTON_DEPEND, new Object[]{attribute.get(Attribute.ATTRIBUTE_FILECHOOSE_FILTER), attribute.exists(Attribute.ATTRIBUTE_FILECHOOSE_TYPE)?attribute.get(Attribute.ATTRIBUTE_FILECHOOSE_TYPE):null,attribute.get(Attribute.ATTRIBUTE_FILECHOOSE_DEPEND),text})
		);
		file.add(fileButton, BorderLayout.EAST);
		return file;
	}
}
